package restless.core.managers {
	
	import com.greensock.plugins.TweenPlugin;
	import com.greensock.plugins.VolumePlugin;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	
	import restless.core.audio.RLEMusic;
	import restless.core.audio.RLESoundEvent
	import restless.core.audio.RLESoundItem;
	import restless.core.interfaces.IUR;
	import restless.core.RestlessEngine;
	
	import flash.events.TimerEvent;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.media.SoundMixer;
	import flash.media.Sound;
	import flash.net.URLRequest;
	import flash.utils.getQualifiedClassName;
	import flash.utils.Timer;
	
	/**
	 * 
	 * Best used with
	 * MP3 Sample Rate: 44.1
	 * 
	 * @author	Matt Przybylski [http://www.reintroducing.com]
	 *	 		Jordan Laine [http://www.mustnotsleepgames.com]
	 * @version 1.6 rle
	 * 
	 */
	 
	public class RLESoundManager {
		
		TweenPlugin.activate([VolumePlugin]);
		
		private var RE:RestlessEngine;
		public var music:RLEMusic;
		
		private var framerate:Number;
		private var beatTimer:Timer;
		private var timerInterval:Number;
		
		private var vBeat:Vector.<RLESoundItem>;
		private var vSounds:Vector.<RLESoundItem>;
		private var vSoundIDs:Vector.<String>;
		
		private var bMusicMuted:Boolean = false;
		private var bSoundMuted:Boolean = false;
		private var nGlobalVolume:Number;
		
		private var tempSoundItem:RLESoundItem;
		private var tempID:String;
		private var tempNum:int;
		
		private var i:int;
		private var nChannels:int;
		private var nMaxChannels:int = 32;
		private var BPM:int;
		
		public function RLESoundManager() {
			RE = RestlessEngine.instance;
			globalVolume = 1;
			framerate = RE.frameRate;
			vSounds = new Vector.<RLESoundItem>;
			vSoundIDs = new Vector.<String>;
			music = new RLEMusic();
			music.volume = globalVolume;
			timerInterval = 1000 / framerate;
			beatTimer = new Timer(timerInterval);
			beatTimer.addEventListener(TimerEvent.TIMER, beat, false, 0, true);
			
		}
		
		public function addSound(sound:Class, volume:Number = 1, id:String = null, beat:Boolean = false):void {
			if (id == null) {
				tempID = String(sound);
				tempID = tempID.substring(7, tempID.length-1);
			} else {
				tempID = id;
			}
			
			i = vSounds.indexOf(sound);
			if ( i > -1) { return; }	
			
			tempSoundItem = new RLESoundItem();
			tempSoundItem.setSound(new sound);
			tempSoundItem.sID = id;
			tempSoundItem.nPosition = 0;
			tempSoundItem.bPause = false;
			tempSoundItem.mute = bSoundMuted;
			tempSoundItem.nStart = 0;
			tempSoundItem.nLoops = 0;
			tempSoundItem.bBeat = beat;
			tempSoundItem.volume = volume;
			
			vSounds.push(tempSoundItem);
			vSoundIDs.push(tempID);
			if (beat) {
				vBeat.push(tempSoundItem);
			}
		}
		
		private function beat(e:Event = null):void {
			i = vBeat.length -1;
			for (i; i > -1; i--) {
				tempSoundItem = vBeat[i];
				tempSoundItem.beat();
			}
		}
		
		public function removeSound(id:String):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.dispose();		
			vSounds.splice(tempNum, 1);
			vSoundIDs.splice(tempNum, 1);	
		}
		
		public function removeAllSounds():void {
			i = vSounds.length-1;
			for (i; i > -1; i--) {
				tempSoundItem = vSounds[i];
				tempSoundItem.dispose();
			}
			
			vSounds.length = 0;
			vSoundIDs.length = 0;
			vBeat.length = 0;
		}
		
		public function playSound(id:String, startTime:Number = 0, loops:int = 0, resumeTween:Boolean = true):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.play(startTime, loops, resumeTween);
		}
		
		public function getChannel():SoundChannel {
			if (nChannels >= nMaxChannels) {
				throw Error("Too many sound channels dood!");
			}
			nChannels++;
			return new SoundChannel();
		}
		
		public function releaseChannel():void {
			nChannels--;
		}
		
		public function set channelsAllowed(num:int):void {
			if (num > 32) {
				nMaxChannels = 32;
				return;
			} else if (num < 1) {
				nMaxChannels = 1;
				return;
			}
			
			nMaxChannels = num;
		}
		
		public function get channelsAllowed():int {
			return nMaxChannels;
		}
		
		public function modSound(id:String, mod:Boolean, rate:Number = 1, tempo:Number = 1, pitch:Number = 1):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.removeMod(); 
			if (!mod) {
				return;
			}
			tempSoundItem.mod(pitch, rate, tempo);
		}
		
		public function pauseSound(id:String, pauseTween:Boolean = true):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.pause(pauseTween);
		}
		
		public function stopSound(id:String):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.stop();
		}
		
		public function playAllSounds(resumeTweens:Boolean = true, currentlyPlayingOnly:Boolean = false):void {
			var id:String;
			i = vSounds.length-1;
			for (i; i > -1; i--) {
				tempSoundItem = vSounds[i];
				id = tempSoundItem.sID;
				if (currentlyPlayingOnly) {
					if (tempSoundItem.bPlaying) {
						playSound(id, 0, 0, resumeTweens);
					}
				} else {
					playSound(id, 0, 0, resumeTweens);
				}
			}
		}
		
		public function pauseAllSounds(pauseTweens:Boolean = true, currentlyPlayingOnly:Boolean = false):void {
			var id:String;
			i = vSounds.length -1;
			for (i; i > -1; i--) {
				tempSoundItem = vSounds[i];
				id = tempSoundItem.sID;
				
				if (currentlyPlayingOnly) {
					if (tempSoundItem.bPlaying) {
						pauseSound(id, pauseTweens);
					}
				} else {
					pauseSound(id, pauseTweens);
				}
			}
		}
		
		public function stopAllSounds(currentlyPlayingOnly:Boolean = false):void {
			
			var id:String;
			
			i = vSounds.length -1;
			for (i; i > -1; i--) {
				tempSoundItem = vSounds[i];
				id = tempSoundItem.sID;
				
				if (currentlyPlayingOnly) {
					if (tempSoundItem.bPlaying) {
						tempSoundItem.stop();
					}
				} else {
					tempSoundItem.stop();
				}
			}
		}
		
		public function fadeSound(id:String, targVolume:Number = 0, fadeLength:Number = 1, stopOnComplete:Boolean = false):void {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			tempSoundItem.fade(targVolume, fadeLength, stopOnComplete);
		}
		
		public function toggleMuteAllSounds():void {
			muteAllSounds(!bSoundMuted);
		}
		
		public function muteAllSounds(bool:Boolean):void {
			if (bool == bSoundMuted) { return; }
			bSoundMuted = bool;
			
			var id:String;
			i = vSounds.length -1;
			
			if (bSoundMuted) {
				for (i; i > -1; i--) {
					tempSoundItem = vSounds[i];
					id = tempSoundItem.sID;
					tempSoundItem.mute = true;
				}
				
			} else {
				for (i; i > -1; i--) {
					tempSoundItem = vSounds[i];
					id = tempSoundItem.sID;
					tempSoundItem.mute = false;
				}
			}
		}
		
		public function muteSytem(bool:Boolean):void {
			var num:Number;
			if (bool) { num = 0; }
			else { num = 1; }
			
			SoundMixer.soundTransform = new SoundTransform(num);
		}
		
		
		public function toggleMuteMusic():void {
			music.mute = !music.mute;
		}
		
		public function set globalVolume(volume:Number):void {
			if (volume > 1) {
				nGlobalVolume = 1;
				return;
			} else if ( volume < 0) {
				nGlobalVolume = 0;
				return;
			}
			
			nGlobalVolume = volume;
			
		}
		
		public function get globalVolume():Number {
			return nGlobalVolume;
		}
		
		public function getSoundItem(id:String):RLESoundItem {
			tempNum = vSoundIDs.indexOf(id);
			tempSoundItem = vSounds[tempNum];
			return tempSoundItem;
		}
		
		public function get sounds():Vector.<RLESoundItem> {
		    return vSounds;
		}
		
		public function get areAllMuted():Boolean {
		    return bSoundMuted;
		}
		
		public function dispose():void {
			
		}
	}
}